#pragma once
#include "../common.hpp"
#include "Vector.hpp"
#undef min
#undef max

namespace zzz{
template <typename T>
class Vector<2, T> : public VectorBase<2, T>
{
protected:
  using VectorBase<2, T>::v;
public:
  //constructor
  Vector(void){}
  Vector(const Vector<2, T>& a):VectorBase<2, T>(a){}
  Vector(const T &a, const T &b){v[0]=a; v[1]=b;}
  Vector(const VectorBase<2, T>& a):VectorBase<2, T>(a){}
  explicit Vector(const T &a):VectorBase<2, T>(a){}
  explicit Vector(const VectorBase<1, T> &a, const T &b):VectorBase<2, T>(a, b){}
  explicit Vector(const VectorBase<3, T> &a):VectorBase<2, T>(a){}
  template<typename T1> explicit Vector(const T1 *p):VectorBase<2, T>(p){}
  template<typename T1> explicit Vector(const Vector<2,T1>& a):VectorBase<2, T>(a){}
  template<typename T1> explicit Vector(const VectorBase<2,T1>& a):VectorBase<2, T>(a){}

  //assign
  inline const Vector<2, T> &operator=(const Vector<2, T>& a){VectorBase<2, T>::operator =(a); return *this;}
  inline void Set(const T &a, const T &b){v[0]=a; v[1]=b;}
  using VectorBase<2, T>::operator=;

  // alias
  inline T& x(){return v[0];}
  inline T& y(){return v[1];}
  inline const T& x() const {return v[0];}
  inline const T& y() const {return v[1];}
};

typedef Vector<2,zint8> Vector2i8;
typedef Vector<2,zuint8> Vector2ui8;
typedef Vector<2,zint8> Vector2i16;
typedef Vector<2,zuint8> Vector2ui16;
typedef Vector<2,zint8> Vector2i32;
typedef Vector<2,zuint8> Vector2ui32;
typedef Vector<2,zint8> Vector2i64;
typedef Vector<2,zuint8> Vector2ui64;
typedef Vector<2,zfloat32> Vector2f32;
typedef Vector<2,zfloat64> Vector2f64;


typedef Vector<2,zuint> Vector2ui;
typedef Vector<2,int> Vector2i;
typedef Vector<2,float> Vector2f;
typedef Vector<2,double> Vector2d;

template<typename T>
inline T Cross(const VectorBase<2, T> &a, const VectorBase<2, T> &b)
{
  return a[0]*b[1]-a[1]*b[0];
}

}
